package com.zf.rabbitmq.producer.delay;

import com.zf.rabbitmq.producer.dead_letter.DeadLetterByTtlConfig;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 延迟消息配置
 * 1、这里使用 https://github.com/rabbitmq/rabbitmq-delayed-message-exchange 插件 实现延迟消息，
 * 该插件提供了一个延迟交换机类型："x-delayed-message"。
 * <p>
 * 2、还可以 借助 TTL + 死信队列 实现延迟消息，可以参考 {@link DeadLetterByTtlConfig } 类中的代码，
 * <p>
 * 这两种方式实现的延迟消息的 优缺点见 rabbitmq-sample\readme.md
 */
@Component
public class DelayMsgByPluginConfig implements InitializingBean {
    public static final String testDelayPluginExchangeName = "test_delay_plugin_direct_exchange";
    public static final String testDelayPluginQueueName = "test_delay_plugin_queue";
    public static final String testDelayPluginRouteKey = "test_delay_plugin_route_key";

    @Autowired
    private AmqpAdmin amqpAdmin;

    /**
     * 借助 rabbitmq-delayed-message-exchange 插件实现延迟消息
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        // 首先要安装 rabbitmq-delayed-message-exchange 插件，该插件提供了一个延迟交换机类型："x-delayed-message"。
        // 声明一个延迟交换机，使用 direct 类型实现，表示投递消息时按照direct的规则去匹配队列。
        // delayed() 操作标识该交换机是延迟交换机，会在声明交换机时 自动添加 "x-delayed-type" 参数，不用再手动添加，
        // 且会在声明时把交换机的类型设置为 "x-delayed-message"，表示是延迟交换机
        Exchange delayExchange = ExchangeBuilder.directExchange(testDelayPluginExchangeName)
                .delayed()
                .build();
        amqpAdmin.declareExchange(delayExchange);

        // 声明队列，接收从延迟交换机发送来的数据
        Queue queue = QueueBuilder.durable(testDelayPluginQueueName).build();
        amqpAdmin.declareQueue(queue);

        // 声明绑定
        Binding binding = BindingBuilder.bind(queue).to(delayExchange).with(testDelayPluginRouteKey).noargs();
        amqpAdmin.declareBinding(binding);
    }
}
